package com.team9.fitness.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.ConcurrentHashMap;
import com.team9.fitness.service.DataReceivedCallback;
import jakarta.annotation.PostConstruct;

/**
 * ZRDDS数据交换服务
 * 实现四种主题的数据交换：
 * 1. User/Action - 用户行为数据（登录、注册、操作等）
 * 2. Exercise/Data - 运动数据（开始运动、结束运动、实时数据等）
 * 3. Diet/Record - 饮食记录数据（添加食物、营养分析等）
 * 4. Community/Activity - 社区活动数据（发帖、评论等）
 * 
 * 使用真实的ZRDDS中间件，不使用模拟实现
 */
@Service
public class ZRDDSDataExchangeService implements DataReceivedCallback {

    private static final Logger log = LoggerFactory.getLogger(ZRDDSDataExchangeService.class);

    // 定义四种主题
    public static final String TOPIC_USER_ACTION = "User/Action";
    public static final String TOPIC_EXERCISE_DATA = "Exercise/Data";
    public static final String TOPIC_DIET_RECORD = "Diet/Record";
    public static final String TOPIC_COMMUNITY_ACTIVITY = "Community/Activity";

    @Autowired
    private ZRDDSDataListener dataListener;

    // 存储最近发布的消息ID
    private final Map<String, String> lastMessageIds = new ConcurrentHashMap<>();

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final AtomicInteger messageCounter = new AtomicInteger(0);

    @Autowired
    private ZRDDSManagerService zrddsManagerService;

    @Autowired
    private CallbackRegistryService callbackRegistryService;

    @Autowired
    private UserService userService;

    /**
     * 初始化时设置回调
     */
    @PostConstruct
    public void initialize() {
        if (zrddsManagerService != null) {
            zrddsManagerService.setDataReceivedCallback(this);
            log.info("ZRDDS数据接收回调已设置");
        }
    }

    /**
     * 发布用户行为数据
     * 使用真实的ZRDDS中间件
     */
    public boolean publishUserAction(String actionType, Long userId, String username,
            Map<String, Object> additionalData) {
        try {
            int messageId = messageCounter.incrementAndGet();
            Map<String, Object> data = new HashMap<>();
            data.put("messageId", messageId);
            data.put("timestamp", LocalDateTime.now().toString());
            data.put("actionType", actionType);
            data.put("userId", userId);
            data.put("username", username);
            data.put("source", "FitnessSystem");

            if (additionalData != null) {
                data.putAll(additionalData);
            }

            String jsonData = objectMapper.writeValueAsString(data);
            boolean success = zrddsManagerService.publishData(TOPIC_USER_ACTION, jsonData);

            if (success) {
                log.info("用户行为数据发布成功: actionType={}, userId={}, username={}, messageId={}", actionType, userId,
                        username, messageId);
                // 存储消息ID，用于后续获取结果
                lastMessageIds.put(actionType + "_" + username, String.valueOf(messageId));
            }

            return success;
        } catch (Exception e) {
            log.error("发布用户行为数据失败: actionType={}, userId={}", actionType, userId, e);
            return false;
        }
    }

    /**
     * 异步发布用户行为数据（支持回调）
     * 使用真实的ZRDDS中间件
     */
    public void publishUserActionAsync(String actionType, Long userId, String username,
            Map<String, Object> additionalData, java.util.function.Consumer<Map<String, Object>> callback) {
        try {
            int messageId = messageCounter.incrementAndGet();
            Map<String, Object> data = new HashMap<>();
            data.put("messageId", messageId);
            data.put("timestamp", LocalDateTime.now().toString());
            data.put("actionType", actionType);
            data.put("userId", userId);
            data.put("username", username);
            data.put("source", "FitnessSystem");

            if (additionalData != null) {
                data.putAll(additionalData);
            }

            // 注册回调
            callbackRegistryService.registerCallback(String.valueOf(messageId), callback, 30); // 30秒超时

            // 异步发布数据
            java.util.concurrent.CompletableFuture.runAsync(() -> {
                try {
                    String jsonData = objectMapper.writeValueAsString(data);
                    boolean success = zrddsManagerService.publishData(TOPIC_USER_ACTION, jsonData);

                    if (success) {
                        log.info("用户行为数据异步发布成功: actionType={}, userId={}, username={}, messageId={}",
                                actionType, userId, username, messageId);
                        // 存储消息ID，用于后续获取结果
                        lastMessageIds.put(actionType + "_" + username, String.valueOf(messageId));

                        // 立即处理业务逻辑并执行回调
                        Map<String, Object> result = processUserAction(actionType, username, additionalData);
                        callbackRegistryService.executeCallback(String.valueOf(messageId), result);
                    } else {
                        // 发布失败，执行错误回调
                        Map<String, Object> errorResult = new HashMap<>();
                        errorResult.put("success", false);
                        errorResult.put("message", "数据发布失败");
                        callbackRegistryService.executeCallback(String.valueOf(messageId), errorResult);
                    }
                } catch (Exception e) {
                    log.error("异步发布用户行为数据失败: actionType={}, userId={}", actionType, userId, e);
                    // 执行错误回调
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("success", false);
                    errorResult.put("message", "数据发布异常: " + e.getMessage());
                    callbackRegistryService.executeCallback(String.valueOf(messageId), errorResult);
                }
            });

        } catch (Exception e) {
            log.error("准备异步发布用户行为数据失败: actionType={}, userId={}", actionType, userId, e);
            // 执行错误回调
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "准备发布数据失败: " + e.getMessage());
            callback.accept(errorResult);
        }
    }

    /**
     * 处理用户行为业务逻辑
     */
    private Map<String, Object> processUserAction(String actionType, String username,
            Map<String, Object> additionalData) {
        try {
            Map<String, Object> result = new HashMap<>();

            if ("LOGIN".equals(actionType)) {
                // 处理登录逻辑
                result = processLogin(username, additionalData);
            } else if ("REGISTER".equals(actionType)) {
                // 处理注册逻辑
                result = processRegister(username, additionalData);
            } else {
                // 其他用户行为
                result.put("success", true);
                result.put("message", "用户行为处理成功");
                result.put("actionType", actionType);
                result.put("username", username);
            }

            return result;
        } catch (Exception e) {
            log.error("处理用户行为失败: actionType={}, username={}", actionType, username, e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "处理用户行为失败: " + e.getMessage());
            return errorResult;
        }
    }

    /**
     * 处理用户登录
     */
    private Map<String, Object> processLogin(String username, Map<String, Object> additionalData) {
        try {
            // 创建登录DTO
            com.team9.fitness.dto.SignInDTO signInDTO = new com.team9.fitness.dto.SignInDTO();
            signInDTO.setUsername(username);
            signInDTO.setPassword((String) additionalData.get("password"));

            // 调用UserService进行登录验证
            org.springframework.http.ResponseEntity<Map<String, Object>> response = userService.signIn(signInDTO);

            if (response.getBody() != null) {
                return response.getBody();
            } else {
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("success", false);
                errorResult.put("message", "登录验证失败");
                return errorResult;
            }
        } catch (Exception e) {
            log.error("处理用户登录失败: username={}", username, e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "登录处理失败: " + e.getMessage());
            return errorResult;
        }
    }

    /**
     * 处理用户注册
     */
    private Map<String, Object> processRegister(String username, Map<String, Object> additionalData) {
        try {
            // 创建注册DTO
            com.team9.fitness.dto.SignUpDTO signUpDTO = new com.team9.fitness.dto.SignUpDTO();
            signUpDTO.setUsername(username);
            signUpDTO.setPassword((String) additionalData.get("password"));
            signUpDTO.setConfirmPassword((String) additionalData.get("confirmPassword"));

            // 调用UserService进行注册
            org.springframework.http.ResponseEntity<Map<String, Object>> response = userService.signUp(signUpDTO);

            if (response.getBody() != null) {
                return response.getBody();
            } else {
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("success", false);
                errorResult.put("message", "注册验证失败");
                return errorResult;
            }
        } catch (Exception e) {
            log.error("处理用户注册失败: username={}", username, e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "注册处理失败: " + e.getMessage());
            return errorResult;
        }
    }

    /**
     * 发布运动数据
     * 使用真实的ZRDDS中间件
     */
    public boolean publishExerciseData(String actionType, Long userId, String exerciseType,
            Map<String, Object> exerciseData) {
        try {
            int messageId = messageCounter.incrementAndGet();
            Map<String, Object> data = new HashMap<>();
            data.put("messageId", messageId);
            data.put("timestamp", LocalDateTime.now().toString());
            data.put("actionType", actionType);
            data.put("userId", userId);
            data.put("exerciseType", exerciseType);
            data.put("source", "FitnessSystem");

            if (exerciseData != null) {
                data.putAll(exerciseData);
            }

            String jsonData = objectMapper.writeValueAsString(data);
            boolean success = zrddsManagerService.publishData(TOPIC_EXERCISE_DATA, jsonData);

            if (success) {
                log.info("运动数据发布成功: actionType={}, userId={}, exerciseType={}, messageId={}", actionType, userId,
                        exerciseType, messageId);
                // 存储消息ID，用于后续获取结果
                if (userId != null) {
                    lastMessageIds.put(actionType + "_" + userId, String.valueOf(messageId));
                } else if (exerciseData != null && exerciseData.get("recordId") != null) {
                    // 对于结束运动，使用recordId作为key
                    lastMessageIds.put(actionType + "_" + exerciseData.get("recordId"), String.valueOf(messageId));
                }
            }

            return success;
        } catch (Exception e) {
            log.error("发布运动数据失败: actionType={}, userId={}, exerciseType={}", actionType, userId, exerciseType, e);
            return false;
        }
    }

    /**
     * 异步发布运动数据（支持回调）
     * 使用真实的ZRDDS中间件
     */
    public void publishExerciseDataAsync(String actionType, Long userId, String exerciseType,
            Map<String, Object> exerciseData, java.util.function.Consumer<Map<String, Object>> callback) {
        try {
            int messageId = messageCounter.incrementAndGet();
            Map<String, Object> data = new HashMap<>();
            data.put("messageId", String.valueOf(messageId));
            data.put("timestamp", LocalDateTime.now().toString());
            data.put("actionType", actionType);
            data.put("userId", userId);
            data.put("exerciseType", exerciseType);
            data.put("source", "FitnessSystem");

            if (exerciseData != null) {
                data.putAll(exerciseData);
            }

            // 注册回调
            callbackRegistryService.registerCallback(String.valueOf(messageId), callback, 30); // 30秒超时

            // 异步发布数据
            java.util.concurrent.CompletableFuture.runAsync(() -> {
                try {
                    String jsonData = objectMapper.writeValueAsString(data);
                    boolean success = zrddsManagerService.publishData(TOPIC_EXERCISE_DATA, jsonData);

                    if (success) {
                        log.info("运动数据异步发布成功: actionType={}, userId={}, exerciseType={}, messageId={}",
                                actionType, userId, exerciseType, messageId);
                        // 存储消息ID，用于后续获取结果
                        if (userId != null) {
                            lastMessageIds.put(actionType + "_" + userId, String.valueOf(messageId));
                        } else if (exerciseData != null && exerciseData.get("recordId") != null) {
                            // 对于结束运动，使用recordId作为key
                            lastMessageIds.put(actionType + "_" + exerciseData.get("recordId"),
                                    String.valueOf(messageId));
                        }

                        // 等待ZRDDS处理完成并通过回调返回结果
                        // 这里不需要立即执行回调，因为ZRDDS会通过数据监听器处理并执行回调
                        log.info("运动数据已发布到ZRDDS，等待异步处理完成: messageId={}", messageId);
                    } else {
                        // 发布失败，执行错误回调
                        Map<String, Object> errorResult = new HashMap<>();
                        errorResult.put("success", false);
                        errorResult.put("message", "数据发布失败");
                        callbackRegistryService.executeCallback(String.valueOf(messageId), errorResult);
                    }
                } catch (Exception e) {
                    log.error("异步发布运动数据失败: actionType={}, userId={}, exerciseType={}", actionType, userId, exerciseType,
                            e);
                    // 执行错误回调
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("success", false);
                    errorResult.put("message", "数据发布异常: " + e.getMessage());
                    callbackRegistryService.executeCallback(String.valueOf(messageId), errorResult);
                }
            });

        } catch (Exception e) {
            log.error("准备异步发布运动数据失败: actionType={}, userId={}, exerciseType={}", actionType, userId, exerciseType, e);
            // 执行错误回调
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "准备发布数据失败: " + e.getMessage());
            callback.accept(errorResult);
        }
    }

    /**
     * 发布饮食记录数据
     * 使用真实的ZRDDS中间件
     */
    public boolean publishDietRecord(String actionType, Long userId, Long recordId,
            Map<String, Object> dietData) {
        try {
            int messageId = messageCounter.incrementAndGet();
            Map<String, Object> data = new HashMap<>();
            data.put("messageId", messageId);
            data.put("timestamp", LocalDateTime.now().toString());
            data.put("actionType", actionType);
            data.put("userId", userId);
            data.put("recordId", recordId);
            data.put("source", "FitnessSystem");

            if (dietData != null) {
                data.putAll(dietData);
            }

            String jsonData = objectMapper.writeValueAsString(data);
            boolean success = zrddsManagerService.publishData(TOPIC_DIET_RECORD, jsonData);

            if (success) {
                log.info("饮食记录数据发布成功: actionType={}, userId={}, recordId={}, messageId={}", actionType, userId,
                        recordId, messageId);
                // 存储消息ID，用于后续获取结果
                lastMessageIds.put(actionType + "_" + recordId, String.valueOf(messageId));
            }

            return success;
        } catch (Exception e) {
            log.error("发布饮食记录数据失败: actionType={}, userId={}, recordId={}", actionType, userId, recordId, e);
            return false;
        }
    }

    /**
     * 异步发布饮食记录数据（支持回调）
     * 使用真实的ZRDDS中间件
     */
    public void publishDietRecordAsync(String actionType, Long userId, Long recordId,
            Map<String, Object> dietData, java.util.function.Consumer<Map<String, Object>> callback) {
        try {
            int messageId = messageCounter.incrementAndGet();
            Map<String, Object> data = new HashMap<>();
            data.put("messageId", messageId);
            data.put("timestamp", LocalDateTime.now().toString());
            data.put("actionType", actionType);
            data.put("userId", userId);
            data.put("recordId", recordId);
            data.put("source", "FitnessSystem");

            if (dietData != null) {
                data.putAll(dietData);
            }

            // 注册回调
            callbackRegistryService.registerCallback(String.valueOf(messageId), callback, 30); // 30秒超时

            // 异步发布数据
            java.util.concurrent.CompletableFuture.runAsync(() -> {
                try {
                    String jsonData = objectMapper.writeValueAsString(data);
                    boolean success = zrddsManagerService.publishData(TOPIC_DIET_RECORD, jsonData);

                    if (success) {
                        log.info("饮食记录数据异步发布成功: actionType={}, userId={}, recordId={}, messageId={}",
                                actionType, userId, recordId, messageId);
                        // 存储消息ID，用于后续获取结果
                        lastMessageIds.put(actionType + "_" + recordId, String.valueOf(messageId));
                    } else {
                        // 发布失败，执行错误回调
                        Map<String, Object> errorResult = new HashMap<>();
                        errorResult.put("success", false);
                        errorResult.put("message", "数据发布失败");
                        callbackRegistryService.executeCallback(String.valueOf(messageId), errorResult);
                    }
                } catch (Exception e) {
                    log.error("异步发布饮食记录数据失败: actionType={}, userId={}, recordId={}", actionType, userId, recordId, e);
                    // 执行错误回调
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("success", false);
                    errorResult.put("message", "数据发布异常: " + e.getMessage());
                    callbackRegistryService.executeCallback(String.valueOf(messageId), errorResult);
                }
            });

        } catch (Exception e) {
            log.error("准备异步发布饮食记录数据失败: actionType={}, userId={}, recordId={}", actionType, userId, recordId, e);
            // 执行错误回调
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "准备发布数据失败: " + e.getMessage());
            callback.accept(errorResult);
        }
    }

    /**
     * 发布社区活动数据
     * 使用真实的ZRDDS中间件
     */
    public boolean publishCommunityActivity(String actionType, Long userId, Long postId,
            Map<String, Object> communityData) {
        try {
            int messageId = messageCounter.incrementAndGet();
            Map<String, Object> data = new HashMap<>();
            data.put("messageId", messageId);
            data.put("timestamp", LocalDateTime.now().toString());
            data.put("actionType", actionType);
            data.put("userId", userId);
            data.put("postId", postId);
            data.put("source", "FitnessSystem");

            if (communityData != null) {
                data.putAll(communityData);
            }

            String jsonData = objectMapper.writeValueAsString(data);
            boolean success = zrddsManagerService.publishData(TOPIC_COMMUNITY_ACTIVITY, jsonData);

            if (success) {
                log.info("社区活动数据发布成功: actionType={}, userId={}, postId={}, messageId={}", actionType, userId,
                        postId, messageId);
                // 存储消息ID，用于后续获取结果
                lastMessageIds.put(actionType + "_" + postId, String.valueOf(messageId));
            }

            return success;
        } catch (Exception e) {
            log.error("发布社区活动数据失败: actionType={}, userId={}, postId={}", actionType, userId, postId, e);
            return false;
        }
    }

    /**
     * 异步发布社区活动数据（支持回调）
     * 使用真实的ZRDDS中间件
     */
    public void publishCommunityActivityAsync(String actionType, Long userId, Long postId,
            Map<String, Object> communityData, java.util.function.Consumer<Map<String, Object>> callback) {
        try {
            int messageId = messageCounter.incrementAndGet();
            Map<String, Object> data = new HashMap<>();
            data.put("messageId", messageId);
            data.put("timestamp", LocalDateTime.now().toString());
            data.put("actionType", actionType);
            data.put("userId", userId);
            data.put("postId", postId);
            data.put("source", "FitnessSystem");

            if (communityData != null) {
                data.putAll(communityData);
            }

            // 注册回调
            callbackRegistryService.registerCallback(String.valueOf(messageId), callback, 30); // 30秒超时

            // 异步发布数据
            java.util.concurrent.CompletableFuture.runAsync(() -> {
                try {
                    String jsonData = objectMapper.writeValueAsString(data);
                    boolean success = zrddsManagerService.publishData(TOPIC_COMMUNITY_ACTIVITY, jsonData);

                    if (success) {
                        log.info("社区活动数据异步发布成功: actionType={}, userId={}, postId={}, messageId={}",
                                actionType, userId, postId, messageId);
                        // 存储消息ID，用于后续获取结果
                        lastMessageIds.put(actionType + "_" + postId, String.valueOf(messageId));
                    } else {
                        // 发布失败，执行错误回调
                        Map<String, Object> errorResult = new HashMap<>();
                        errorResult.put("success", false);
                        errorResult.put("message", "数据发布失败");
                        callbackRegistryService.executeCallback(String.valueOf(messageId), errorResult);
                    }
                } catch (Exception e) {
                    log.error("异步发布社区活动数据失败: actionType={}, userId={}, postId={}", actionType, userId, postId, e);
                    // 执行错误回调
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("success", false);
                    errorResult.put("message", "数据发布异常: " + e.getMessage());
                    callbackRegistryService.executeCallback(String.valueOf(messageId), errorResult);
                }
            });

        } catch (Exception e) {
            log.error("准备异步发布社区活动数据失败: actionType={}, userId={}, postId={}", actionType, userId, postId, e);
            // 执行错误回调
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("message", "准备发布数据失败: " + e.getMessage());
            callback.accept(errorResult);
        }
    }

    /**
     * 处理接收到的数据
     * 通过ZRDDS的真实数据传输接收
     */
    public void handleReceivedData(String topicName, String data) {
        try {
            log.info("收到ZRDDS数据: topic={}, data={}", topicName, data);

            switch (topicName) {
                case TOPIC_USER_ACTION:
                    dataListener.handleUserAction(data);
                    break;
                case TOPIC_EXERCISE_DATA:
                    dataListener.handleExerciseData(data);
                    break;
                case TOPIC_DIET_RECORD:
                    dataListener.handleDietRecord(data);
                    break;
                case TOPIC_COMMUNITY_ACTIVITY:
                    dataListener.handleCommunityActivity(data);
                    break;
                default:
                    log.warn("未知的主题: {}", topicName);
            }
        } catch (Exception e) {
            log.error("处理接收到的数据失败: topic={}, data={}", topicName, data, e);
        }
    }

    /**
     * 实现DataReceivedCallback接口
     * 接收来自ZRDDS的真实数据
     */
    @Override
    public void onDataReceived(String topicName, String data) {
        handleReceivedData(topicName, data);
    }

    /**
     * 订阅所有主题
     * 使用真实的ZRDDS中间件
     */
    public void subscribeAllTopics() {
        subscribeTopic(TOPIC_USER_ACTION);
        subscribeTopic(TOPIC_EXERCISE_DATA);
        subscribeTopic(TOPIC_DIET_RECORD);
        subscribeTopic(TOPIC_COMMUNITY_ACTIVITY);
    }

    /**
     * 订阅指定主题
     * 使用真实的ZRDDS中间件
     */
    public boolean subscribeTopic(String topicName) {
        return zrddsManagerService.subscribeTopic(topicName);
    }

    /**
     * 取消订阅指定主题
     * 使用真实的ZRDDS中间件
     */
    public boolean unsubscribeTopic(String topicName) {
        return zrddsManagerService.unsubscribeTopic(topicName);
    }

    /**
     * 获取已订阅的主题列表
     */
    public java.util.Set<String> getSubscribedTopics() {
        return zrddsManagerService.getSubscribedTopics();
    }

    /**
     * 检查ZRDDS是否已初始化
     */
    public boolean isInitialized() {
        return zrddsManagerService.isInitialized();
    }

    /**
     * 获取消息计数器
     */
    public int getMessageCount() {
        return messageCounter.get();
    }
}
